package chainSimplification.vo;

import java.util.HashMap;


import com.jme.math.Matrix3f;
import com.jme.math.Quaternion;
import com.jme.math.Vector3f;
import com.jme.scene.Node;
import com.jme.scene.SharedMesh;
import com.jme.scene.SharedNode;
import com.jme.scene.shape.*;

import dviz.tools.ModelRepository;
import dviz.visualSystem.impl.AnimationObject;

// This is the visual object that can be used to visualize Java Objects
// By using @ObjectMap("sphere")
public class PlaneVO extends AnimationObject {
	float x, y, z;
	float ox, oy, oz;
	float speedX, speedY, speedZ;
	float autoTolarence = -1;

	public PlaneVO(HashMap<String, Object> initVector) {
		super(initVector);

		// Getting the Root Node for this Object to be rendered onto the screen
		Node renderNode = getRenderNode();
		// Create a new sphere to be rendered onto screen (JMonkeyEngine API)
		// Sphere sphere = new Sphere("", new Vector3f(), 10, 10, 1);
		// sphere.setLocalRotation(new Quaternion(new float[] {
		// (float) Math.PI / 2f, 0, 0 }));
		// sphere.setLocalScale(0.2f);
		// Box sphere = new Box("", new Vector3f(-1, -1, -1),
		// new Vector3f(1, 1, 1));
		// Attach this object onto the render root node
		SharedNode mesh = new SharedNode((Node) ModelRepository.get()
				.getRepository().get("plane"));
		renderNode.attachChild(mesh);
		if (initVector.keySet().contains("size")) {
			float size = new Float(initVector.get("size").toString());
			setSize(size);
		}
		if (initVector.keySet().contains("autoDirection")) {
			autoTolarence = new Float(initVector.get("autoDirection")
					.toString());
		}
	}

	/**
	 * @param size
	 * @uml.property name="size"
	 */
	public void setSize(float size) {
		getRenderNode().setLocalScale(size);
	}

	/**
	 * @param x
	 * @uml.property name="x"
	 */
	public void setX(float x) {
		this.x = x;
		getRenderNode().getLocalTranslation().setX(x);
	}

	public float getSpeedX() {
		return speedX;
	}

	public void setSpeedX(float speedX) {
		this.speedX = speedX;
	}

	public float getSpeedY() {
		return speedY;
	}

	public void setSpeedY(float speedY) {
		this.speedY = speedY;
	}

	public float getSpeedZ() {
		return speedZ;
	}

	public void setSpeedZ(float speedZ) {
		this.speedZ = speedZ;
	}

	@Override
	public void renderUpdate(float fpt) {
		// TODO Auto-generated method stub
		super.renderUpdate(fpt);
		if (autoTolarence >= 0)
			deriveSpeed();
		updateOrientation();
	}

	public void deriveSpeed() {
		float len = (float) Math
				.sqrt((this.x - ox) * (this.x - ox) + (this.y - oy)
						* (this.y - oy) + (this.z - oz) * (this.z - oz));
		if (len > autoTolarence) {
			speedX = this.x - ox;
			speedY = this.y - oy;
			speedZ = this.z - oz;

			speedX /= len;
			speedY /= len;
			speedZ /= len;
			ox = this.x;
			oy = this.y;
			oz = this.z;
		}
	}

	public void updateOrientation() {
		Matrix3f rot = new Matrix3f();
		Vector3f vX = new Vector3f(speedZ, 0, -speedX);
		Vector3f vZ = new Vector3f(speedX, speedY, speedZ);
		Vector3f vY = vZ.cross(vX);
		if (vY.lengthSquared() == 0 || vX.lengthSquared() == 0
				|| vZ.lengthSquared() == 0)
			return;
		vY.normalizeLocal();
		vX.normalizeLocal();
		rot.fromAxes(vX, vY, vZ);
		getRenderNode().setLocalRotation(rot);
	}

	/**
	 * @param y
	 * @uml.property name="y"
	 */
	public void setY(float y) {
		this.y = y;
		getRenderNode().getLocalTranslation().setY(y);
	}

	/**
	 * @param y
	 * @uml.property name="y"
	 */
	public void setZ(float z) {
		this.z = z;
		getRenderNode().getLocalTranslation().setZ(z);
	}

}
